package cn.vivi.recyclercomp.fragment;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.AdapterDataObserver;
import android.support.v7.widget.RecyclerView.ItemDecoration;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import cn.vivi.recyclercomp.DividerItemDecoration;
import cn.vivi.recyclercomp.NetUtils;
import cn.vivi.recyclercomp.R;
import cn.vivi.recyclercomp.Status;
import cn.vivi.recyclercomp.StatusFragment;
import cn.vivi.recyclercomp.adapter.RecyclerViewBaseAdapter;

public abstract class RecyclerViewBaseFragment extends StatusFragment implements
		AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener {

	private static final String TAG = RecyclerViewBaseFragment.class.getSimpleName();
	private static final String KEY_ID = "key_id";

	private RecyclerView mRecyclerView;
	private SwipeRefreshLayout mRefreshLayout;

	private RecyclerViewBaseAdapter mAdapter;
	private LoadingLayout mLoadingLayout;
	private RecyclerView.ItemAnimator mItemAnimator = null;
	private List<RecyclerView.ItemDecoration> mItemDecorations = new ArrayList();
	private LayoutManager mLayoutManager;

	private boolean mAutoLoading = true; // 自动加载
	private int mTriggerLoadItemCount = 3; // 触发下载的item数量；剩下多少项的时候自动加载

	/**
	 * 加载状态（针对底部的加载UI）
	 * 
	 * 包括4种状态：
	 * IDLE 初始状态 没加载前的状态， 或者一次加载完成后回到idle状态
	 * LOADING 加载中。。。， 注意，自动加载的时候，当用户浏览到倒数某个位置的Item时，会自动由IDLE切换到LOADING，并且调用onStartLoading方法
	 * LOADING_ERROR 加载失败，如网络断开等，需要用户点击后方可继续加载
	 * LOADING_FINISH 加载完成， 这里请注意， 这并不是表示某次加载完成， 而是说已经加载了所有的数据。此状态会提示用户类似“已经加载所有数据”的信息
	 * LOADING__NETWORK_UNREACH
	 * 
	 * @author Vivi Peng
	 * @date 2015-06-17
	 * 
	 */
	public enum LoadingState {
		IDLE, LOADING, ERROR, FINISH, INVALID_NETWORK
	};

	protected LoadingState loadingState;


	public RecyclerViewBaseFragment() {
	}


	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}


	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View view = super.onCreateView(inflater, container, savedInstanceState);
		initialize();
		return view;
	}


	@Override
	public View createDataContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View view = getRecyclerViewContainer(inflater);
		mRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh_layout);
		mRefreshLayout.setColorSchemeResources(android.R.color.holo_purple, android.R.color.holo_blue_bright,
				android.R.color.holo_orange_light, android.R.color.holo_red_light);
		setOnSwipeRefreshingListener(new SwipeRefreshLayout.OnRefreshListener() {

			@Override
			public void onRefresh() {
				onStartRefreshing();
			}
		});

		mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
		mItemAnimator = mRecyclerView.getItemAnimator();
		mItemAnimator.setSupportsChangeAnimations(true);
		mRecyclerView.setHasFixedSize(true);

		RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(getActivity(),
				DividerItemDecoration.VERTICAL_LIST);

		mItemDecorations.add(itemDecoration);
		mRecyclerView.addItemDecoration(itemDecoration);
		mRecyclerView.addOnScrollListener(new OnScrollListener() {

			@Override
			public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
				// 自动加载
				if (!mAutoLoading) {
					return;
				}

				if (mAdapter != null && loadingState == LoadingState.IDLE) {
					// 如果itemCount超过2*mTriggerLoadItemCount个
					if (mAdapter.getItemCount() > 2 * mTriggerLoadItemCount) {
						if (mLayoutManager != null) {
							View item = mLayoutManager.findViewByPosition(mAdapter.getItemCount()
									- mTriggerLoadItemCount);
							if (item != null && item.getVisibility() == View.VISIBLE) {
								Log.i(TAG, "item " + (mAdapter.getItemCount() - mTriggerLoadItemCount)
										+ "is visible, start loading");
								startLoading();
							}
						}
					}
				}

				super.onScrolled(recyclerView, dx, dy);
			}

		});

		mAdapter = createAdapter();
		if (mAdapter != null) {
			setHeaderView(createHeaderView(inflater));
			setLoadingLayout(createLoadingLayout(inflater));
			mAdapter.setOnItemClickListener(this);
			mAdapter.setOnItemLongClickListener(this);
			mAdapter.registerAdapterDataObserver(new AdapterDataObserver() {

				@Override
				public void onItemRangeInserted(int positionStart, int itemCount) {
					if (isEmpty()) {
						setStatus(Status.EMPTY);
					} else {
						setStatus(Status.CONTENT);
					}
					super.onItemRangeInserted(positionStart, itemCount);
				}


				@Override
				public void onItemRangeRemoved(int positionStart, int itemCount) {
					if (isEmpty()) {
						setStatus(Status.EMPTY);
					} else {
						setStatus(Status.CONTENT);
					}
					super.onItemRangeRemoved(positionStart, itemCount);
				}
			});
			mRecyclerView.setAdapter(mAdapter);
			mLayoutManager = createLayoutManager();
			mRecyclerView.setLayoutManager(mLayoutManager);
		} else {
			Log.w(TAG, "adapter 为空");
		}
		return view;
	}


	private void setHeaderView(View headerView) {
		if (headerView != null) {
			RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(
					RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT);
			headerView.setLayoutParams(lp);
			mAdapter.setHeaderView(headerView);
		}
		
	}


	public View getRecyclerViewContainer(LayoutInflater inflater) {
		return inflater.inflate(R.layout.fragment_recyclerview, null);
	}


	public abstract LayoutManager createLayoutManager();


	/**
	 * 初始化
	 * 
	 * 可以在这个方法里根据自己的需求做自定义， 比如loadingLayout，setRefreshLayoutEnable(false)等等
	 * 
	 */
	protected void initialize() {

	}


	protected void startLoading() {
		if (NetUtils.getNetworkStatus(getActivity()) == NetUtils.NETWORK_STATE_IDLE) {
			if (isEmpty()) {
				setStatus(Status.EMPTY_INVALID_NEWWORK);
			} else {
				setStatus(Status.CONTENT);
				setLoadingState(LoadingState.INVALID_NETWORK);
			}
			return;
		}
		if (isEmpty()) {
			setStatus(Status.EMPTY_REFRESHING);
		} else {
			setStatus(Status.CONTENT);
			setLoadingState(LoadingState.LOADING);
		}
		onStartLoading();

	}


	public RecyclerView getRecyclerView() {
		return mRecyclerView;
	}


	public RecyclerViewBaseAdapter getAdapter() {
		return mAdapter;
	}


	/**
	 * 回调方法，创建adapter
	 * 
	 * @return
	 */
	public abstract RecyclerViewBaseAdapter createAdapter();


	public View createHeaderView(LayoutInflater inflater) {
		return null;
	}


	public LoadingLayout createLoadingLayout(LayoutInflater inflater) {
		return null;
	}


	/**
	 * 回调方法，创建LoadingLayout
	 * 
	 * @return
	 */
	private LoadingLayout createDefaultLoadingLayout() {
		TextView idle = new TextView(getActivity());
		idle.setText("idle");
		TextView finish = new TextView(getActivity());
		finish.setText("所有数据加载完毕");
		TextView error = new TextView(getActivity());
		error.setText("加载失败");
		error.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				startLoading();

			}
		});
		TextView unreachNetView = new TextView(getActivity());
		error.setText("连接网络失败");
		ProgressBar loading = new ProgressBar(getActivity());
		loading.setIndeterminate(true);

		LoadingLayout layout = new LoadingLayout(getActivity(), idle, loading, error, finish, unreachNetView);
		return layout;
	}


	public void setLoadingLayout(LoadingLayout loadingLayout) {
		mLoadingLayout = loadingLayout;
		mAdapter.setLoaidngLayout(mLoadingLayout);
		if (mLoadingLayout != null) {
			mLoadingLayout.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					if (mLoadingLayout.mState == LoadingState.ERROR
							|| mLoadingLayout.mState == LoadingState.IDLE) {
						startLoading();
					}

				}
			});
		}
	}


	/**
	 * 回调方法，开始加载更多
	 */
	public abstract void onStartLoading();


	/**
	 * 回调方法，开始刷新
	 */
	public void onStartRefreshing() {
	}


	/**
	 * 隐藏刷新控件
	 * 
	 */
	public void hideRefreshView() {
		mRefreshLayout.setRefreshing(false);
	}


	/**
	 * 显示刷新控件
	 * 
	 */
	public void showRefreshView() {
		mRefreshLayout.setRefreshing(true);
	}


	/**
	 * 设置是否需要下拉刷新的功能
	 * 
	 * @param enable
	 */
	public void setRefreshLayoutEnabled(boolean enable) {
		mRefreshLayout.setEnabled(enable);
	}

	private SwipeRefreshLayout.OnRefreshListener mRefreshListener = null;


	/**
	 * 设置向下滑动刷新的listener
	 * user一般不需要设置这个东西，回调onStartRefreshing足够了。
	 * 
	 * @param listener
	 */
	public void setOnSwipeRefreshingListener(SwipeRefreshLayout.OnRefreshListener listener) {
		mRefreshListener = listener;
		mRefreshLayout.setOnRefreshListener(mRefreshListener);
	}


	private void setLoadingState(LoadingState state) {
		if (loadingState != state) {
			loadingState = state;
			if (mLoadingLayout != null) {
				mLoadingLayout.setState(loadingState);
			}
		}

	}

	/**
	 * 为用户提供的设置状态的统一接口，屏蔽LoadingState和StausFragment中的Status
	 * 
	 * LOAD_STATE_END // 完成所有的数据请求
	 * LOAD_STATE_ERROR //错误， 可能是解析有问题，或者是请求的参数不正确
	 * LOAD_STATE_INVALID_NETWORK //遇到网络问题
	 * LOAD_STATE_FINISH //完成某一次的load
	 * 
	 * @author Administrator
	 * 
	 */
	public static enum LoadState {
		END, ERROR, INVALID_NETWORK, FINISH
	};


	public void onStateChanged(LoadState state) {
		// 处理loadingState
		LoadingState loadingState = convert2LoadingState(state);
		setLoadingState(loadingState);

		// 处理StatusFragment的Status
		// 不为空的时候只要处理loadingState就够了，当为空的时候就要处理Status
		if (isEmpty()) {
			if (state == LoadState.ERROR) {
				setStatus(Status.EMPTY_ERROR);
			} else if (state == LoadState.INVALID_NETWORK) {
				setStatus(Status.EMPTY_INVALID_NEWWORK);
			} else if(state == LoadState.END) {
				setStatus(Status.EMPTY);
			}
		}
	}


	private LoadingState convert2LoadingState(LoadState state) {
		switch (state) {
		case END:
			return LoadingState.FINISH;

		case ERROR:
			return LoadingState.ERROR;

		case FINISH:
			return LoadingState.IDLE;

		case INVALID_NETWORK:
			return LoadingState.INVALID_NETWORK;

		default:
			return LoadingState.IDLE;
		}

	}


	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int position, long itemId) {

	}


	@Override
	public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int position, long itemId) {

		return false;
	}


	public void clearDecorations() {
		if (mItemDecorations != null && mItemDecorations.size() > 0) {
			for (ItemDecoration itemDec : mItemDecorations) {
				getRecyclerView().removeItemDecoration(itemDec);
			}
		}
	}


	public boolean isEmpty() {
		if (mAdapter != null) {
			if (mAdapter.getDataCount() > 0) {
				return false;
			}
		}
		return true;
	}


	/**
	 * 设置触发自动加载的item的剩余数量
	 * 
	 * @param itemCount
	 */
	public void setTriggerLoadItemCount(int itemCount) {
		this.mTriggerLoadItemCount = itemCount;
	}


	/**
	 * 是否自动加载
	 * 
	 * @param auto
	 */
	public void setAutoLoading(boolean auto) {
		mAutoLoading = auto;
	}

	public static class LoadingLayout extends LinearLayout {

		private LoadingState mState;
		private View mIdleLayout; // 对应 状态 IDLE
		private View mLoadingLayout; // 对应 状态 LOADING
		private View mErrorLayout;// 对应 状态 LOADING_ERROR
		private View mFinishLayout;// 对应 状态 LOADING_FINISH
		private View mUnreachNetLayout;// 对应 状态 LOADING_UNREACH_NETWORK


		public LoadingLayout(Context context, View idleLayout, View loadingLayout, View errorLayout,
				View finishLayout, View unreachNetLayout) {
			super(context);
			setGravity(Gravity.CENTER);
			RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(
					RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT);
			setLayoutParams(lp);
			mIdleLayout = idleLayout;
			mLoadingLayout = loadingLayout;
			mErrorLayout = errorLayout;
			mFinishLayout = finishLayout;
			mUnreachNetLayout = unreachNetLayout;
			setState(LoadingState.IDLE);
		}


		public LoadingLayout(Context context, AttributeSet attrs) {
			super(context, attrs);

		}


		public void setState(LoadingState state) {
			if (state != mState) {
				mState = state;
				View currLayout = getLayoutBy(mState);
				this.removeAllViews();
				this.addView(currLayout);

			}
		}


		private View getLayoutBy(LoadingState state) {
			switch (state) {
			case IDLE:
				return mIdleLayout;
			case LOADING:
				return mLoadingLayout;
			case ERROR:
				return mErrorLayout;
			case FINISH:
				return mFinishLayout;
			case INVALID_NETWORK:
				return mUnreachNetLayout;
			default:
				return mIdleLayout;
			}
		}

	}

}
